using System.Configuration;
using Gl.SettingsManager.Providers.ConfigurationSections;

namespace Gl.SettingsManager.Providers
{
	internal class ConfigurationFileSettingsProvider : ISettingsProvider
	{
		private ConfigurationUserLevel _userLevel = ConfigurationUserLevel.PerUserRoamingAndLocal;
		private Configuration _config;
		private SettingsSection _settingsSection;

		public ConfigurationUserLevel UserLevel
		{
			get { return _userLevel; }
			set { _userLevel = value; }
		}

		private SettingsSection AddConfigurationSettingsSection()
		{
			SettingsSection section = new SettingsSection();

			section.SectionInformation.AllowDefinition = ConfigurationAllowDefinition.MachineToApplication;
			section.SectionInformation.AllowExeDefinition = ConfigurationAllowExeDefinition.MachineToLocalUser;

			_config.Sections.Add(SettingsSectionXml.SettingsSectionName, section);

			return section;
		}

		#region ISettingsProvider Members

		SettingsCollection ISettingsProvider.GetSettings(string typeName, string context)
		{
			SettingsCollection collection = _settingsSection.GetCollection(typeName, context);
			if (collection == null)
			{
				collection = new SettingsCollection(typeName, context);
				_settingsSection.AddSettings(collection);
			}
			return collection;
		}

		void ISettingsProvider.Save()
		{
			_settingsSection.SectionInformation.ForceSave = true;
			try
			{
				// trying to save configuration
				_config.Save(ConfigurationSaveMode.Full);
			}
			catch (ConfigurationErrorsException)
			{
				// seems like configuration has been changed from the outside,
				// we can reload configuration, this wont rewrite current configuration.
				_config = ConfigurationManager.OpenExeConfiguration(_userLevel);
				_config.Save(ConfigurationSaveMode.Full);
			}
		}

		void ISettingsProvider.InitializeProvider()
		{
			_config = ConfigurationManager.OpenExeConfiguration(_userLevel);

			if (_config.Sections[SettingsSectionXml.SettingsSectionName] != null)
			{

				_settingsSection = (SettingsSection)
					_config.Sections[SettingsSectionXml.SettingsSectionName];

				return;
			}
			else
			{
				_settingsSection = AddConfigurationSettingsSection();
			}
		}

		bool ISettingsProvider.IsInitialized
		{
			get
			{
				return (_config != null && _settingsSection != null);
			}
		}

		public void ResetSettings()
		{
			_settingsSection.Clear();
			((ISettingsProvider)this).Save();
		}

		#endregion
	}
}
